
/* Generated by Interface Builder */

#import "SphereDrawerObject.h"
#import "SphereControl.h"
#import <math.h>
#import <dpsclient/wraps.h>
#import <appkit/appkit.h>
#import "DrawPoly.h"

#define PI (3.14159265)

typedef float vector3D[3];

typedef int boolean;
typedef struct PointThreeD {
	float x,y,z;
} PointThreeD;
 
typedef struct PointTwoD {
	float x,y;
} PointTwoD;

boolean clipFlag=FALSE, shadeFlag=FALSE;
float gray, sinTheta, cosTheta, sinPhi, cosPhi, xMiddle=0, yMiddle=0;
int xSize = 400, ySize = 400;

/***************************************************************/

void CrossXYZ(v1, v2, crossProd)
	vector3D v1, v2, crossProd;
{
	crossProd[0] = v1[1] * v2[2] - v1[2] * v2[1];
	crossProd[1] = v1[2] * v2[0] - v1[0] * v2[2];
	crossProd[2] = v1[0] * v2[1] - v1[1] * v2[0];
}

/***************************************************************/

boolean PolyVisible(poly)
	PointThreeD *poly;
{
	vector3D v1, v2, cross;
	
	v1[0] = poly[0].x - poly[1].x;
	v1[1] = poly[0].y - poly[1].y;
	v1[2] = poly[0].z - poly[1].z;

	v2[0] = poly[2].x - poly[1].x;
	v2[1] = poly[2].y - poly[1].y;
	v2[2] = poly[2].z - poly[1].z;

	CrossXYZ(v1, v2, cross);
	if (cross[2] < 0) return (TRUE);
	else return (FALSE);
	
}

/***************************************************************/

void CalcLight(poly)
	PointThreeD *poly;
{
	vector3D v1, v2, cross;
	
	v1[0] = poly[0].x - poly[1].x;
	v1[1] = poly[0].y - poly[1].y;
	v1[2] = poly[0].z - poly[1].z;

	v2[0] = poly[2].x - poly[1].x;
	v2[1] = poly[2].y - poly[1].y;
	v2[2] = poly[2].z - poly[1].z;

	CrossXYZ(v1, v2, cross);
	gray = -cross[2] / sqrt(cross[0]*cross[0] + cross[1]*cross[1] + cross[2]*cross[2]);
}

/***************************************************************/

void Rotate(px, py, pz)
	float *px, *py, *pz;
{
	float xt, yt;
	
	xt = *pz * sinTheta + *px * cosTheta;
	*pz = *pz * cosTheta - *px * sinTheta;
	*px = xt;
	
	yt = *py * cosPhi - *pz * sinPhi;
	*pz = *py * sinTheta + *pz * cosPhi;
	*py = yt;
}

/***************************************************************/

void DrawPolygon(curPoly)
	PointThreeD curPoly[];
{
	boolean drawFlag=FALSE;
	
	if (shadeFlag==TRUE) CalcLight(curPoly);
	
	Rotate(&curPoly[0].x, &curPoly[0].y, &curPoly[0].z);
	Rotate(&curPoly[1].x, &curPoly[1].y, &curPoly[1].z);
	Rotate(&curPoly[2].x, &curPoly[2].y, &curPoly[2].z);
	Rotate(&curPoly[3].x, &curPoly[3].y, &curPoly[3].z);

	if (clipFlag==TRUE) drawFlag = PolyVisible(curPoly);
	if ((clipFlag && drawFlag) || (clipFlag == FALSE))
	{
		if (shadeFlag==FALSE)
		
			DrawPoly4(xMiddle + curPoly[0].x, yMiddle + curPoly[0].y,
					  xMiddle + curPoly[1].x, yMiddle + curPoly[1].y,
					  xMiddle + curPoly[2].x, yMiddle + curPoly[2].y,
					  xMiddle + curPoly[3].x, yMiddle + curPoly[3].y);
		else
		
			DrawPoly4s(xMiddle + curPoly[0].x, yMiddle + curPoly[0].y,
					   xMiddle + curPoly[1].x, yMiddle + curPoly[1].y,
					   xMiddle + curPoly[2].x, yMiddle + curPoly[2].y,
					   xMiddle + curPoly[3].x, yMiddle + curPoly[3].y, 
					   gray);
				
	
	}
}

void DrawPolygon3(curPoly)
	PointThreeD curPoly[];
{
	boolean drawFlag=FALSE;
	
	if (shadeFlag==TRUE) CalcLight(curPoly);
	
	Rotate(&curPoly[0].x, &curPoly[0].y, &curPoly[0].z);
	Rotate(&curPoly[1].x, &curPoly[1].y, &curPoly[1].z);
	Rotate(&curPoly[2].x, &curPoly[2].y, &curPoly[2].z);

	if (clipFlag==TRUE) drawFlag = PolyVisible(curPoly);
	if ((clipFlag && drawFlag) || (clipFlag == FALSE))
		{
		if (shadeFlag==FALSE)
		
			DrawPoly3(xMiddle + curPoly[0].x, yMiddle + curPoly[0].y,
					  xMiddle + curPoly[1].x, yMiddle + curPoly[1].y,
					  xMiddle + curPoly[2].x, yMiddle + curPoly[2].y);
		else
			DrawPoly3s(xMiddle + curPoly[0].x, yMiddle + curPoly[0].y,
					   xMiddle + curPoly[1].x, yMiddle + curPoly[1].y,
					   xMiddle + curPoly[2].x, yMiddle + curPoly[2].y,
					   gray);

		}
}

/***************************************************************/





@implementation SphereDrawerObject

- init
{
	[super init];
	return self;
}

- computeSphere
{
	float step1=0, step2=0, count1=0, count2=0, s1=0, s2=0, c1=0, c2=0, ts1=0, ts2=0, tc1=0, tc2=0;
	int radius=0;
	PointThreeD curPoly[4];
	
	xMiddle = xSize / 2;
	yMiddle = ySize / 2;

	sinTheta = sin(-[sphereControlPtr readTheta]/180.0*PI);
	sinPhi = sin([sphereControlPtr readPhi]/180.0*PI);
	cosTheta = cos(-[sphereControlPtr readTheta]/180.0*PI);
	cosPhi = cos([sphereControlPtr readPhi]/180.0*PI);
	
	
	step1 = PI / [sphereControlPtr readLat];
	step2 = PI / [sphereControlPtr readLong];
	radius = [sphereControlPtr readRadius];
	clipFlag=[sphereControlPtr readHideFlag];
	shadeFlag=[sphereControlPtr readShadeFlag];


/************ Draw Top Row *******************/
	c1 = 1;
	s1 = 0;
	tc1 = cos(step1);
	ts1 = sin(step1);
	for (count2 = 0; count2 < PI * 2; count2 = count2 + step2)
	{
		curPoly[0].x=0;
		curPoly[0].y=radius;
		curPoly[0].z=0;

		c2 = cos(count2);
		s2 = sin(count2);
		tc2 = cos(count2+step2);
		ts2 = sin(count2+step2);
			
		curPoly[1].x = ts1 * tc2 * radius;
		curPoly[1].y = tc1 * radius;
		curPoly[1].z = ts1 * ts2 * radius;

		curPoly[2].x = ts1 * c2 * radius;
		curPoly[2].y = tc1 * radius;
		curPoly[2].z = ts1 * s2 * radius;

		DrawPolygon3(curPoly);
		
		if ([sphereControlPtr readAutoDraw]==FALSE) PSflushgraphics();
	}

/************ Draw Body of Sphere *******************/
	for (count1 = step1; count1 < (PI-step1); count1 = count1 + step1)
	{
		c1 = cos(count1);
		s1 = sin(count1);
		tc1 = cos(count1+step1);
		ts1 = sin(count1+step1);
		
		for (count2 = 0; count2 < PI * 2; count2 = count2 + step2)
		{
			c2 = cos(count2);
			s2 = sin(count2);
			tc2 = cos(count2+step2);
			ts2 = sin(count2+step2);
			
			curPoly[0].x = s1 * c2 * radius;
			curPoly[0].y = c1 * radius;
			curPoly[0].z = s1 * s2 * radius;

			curPoly[1].x = s1 * tc2 * radius;
			curPoly[1].y = c1 * radius;
			curPoly[1].z = s1 * ts2 * radius;
			
			curPoly[2].x = ts1 * tc2 * radius;
			curPoly[2].y = tc1 * radius;
			curPoly[2].z = ts1 * ts2 * radius;
			
			curPoly[3].x = ts1 * c2 * radius;
			curPoly[3].y = tc1 * radius;
			curPoly[3].z = ts1 * s2 * radius;
			
			DrawPolygon(curPoly);
		
			if ([sphereControlPtr readAutoDraw]==FALSE) PSflushgraphics();
		}
	}

/************ Draw Bottom Row *******************/
	c1 = -1;
	s1 = 0;
	tc1 = cos(PI-step1);
	ts1 = sin(PI-step1);
	for (count2 = 0; count2 < PI * 2; count2 = count2 + step2)
	{
		curPoly[0].x=0;
		curPoly[0].y=-radius;
		curPoly[0].z=0;

		c2 = cos(count2);
		s2 = sin(count2);
		tc2 = cos(count2+step2);
		ts2 = sin(count2+step2);

		curPoly[1].x = ts1 * c2 * radius;
		curPoly[1].y = tc1 * radius;
		curPoly[1].z = ts1 * s2 * radius;
			
		curPoly[2].x = ts1 * tc2 * radius;
		curPoly[2].y = tc1 * radius;
		curPoly[2].z = ts1 * ts2 * radius;

		DrawPolygon3(curPoly);
		
		if ([sphereControlPtr readAutoDraw]==FALSE) PSflushgraphics();
	}

	return self;
}


@end
